package com.txsj.scan.http.requestframework;

import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.util.Log;

import com.txsj.scan.BuildConfig;
import com.txsj.scan.MyApplication;
import com.txsj.scan.http.UrlInterface;
import com.txsj.scan.utils.MD5Util;
import com.txsj.scan.utils.PreferenceUtil;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.FormBody;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;


public class RetrofitManager {


    private final Retrofit retrofit;

    private static class SingleHolder {
        private static final RetrofitManager _INSTANT = new RetrofitManager(UrlInterface.rootUrl);
    }

    public static RetrofitManager getDefault() {
        return SingleHolder._INSTANT;
    }


    public RetrofitManager(String baseUrl) {
        retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .addConverterFactory(GsonConverterFactory.create())
//                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .client(buildOKHttpClient())
                .build();

    }

    private OkHttpClient buildOKHttpClient() {
        //缓存路径
        File cacheFile = new File(MyApplication.getInstance().getCacheDir().getAbsolutePath(), "HttpCache");

        Cache cache = new Cache(cacheFile, 1024 * 1024 * 10);//缓存文件为10MB
        Log.e("11","cache"+"----"+cache);

        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        if (BuildConfig.DEBUG) {
            interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        }else {
            interceptor.setLevel(HttpLoggingInterceptor.Level.BASIC);
        }
        //公共参数
//        Map<String, String> map = new HashMap<>();
//        map.put("source", "android");
//        map.put("appVersion", "101");
//        PublicParamInterceptor publicParamInterceptor = new PublicParamInterceptor(map);
        return new OkHttpClient.Builder()
                .connectTimeout(20000, TimeUnit.MILLISECONDS)
                .readTimeout(20000, TimeUnit.MILLISECONDS)
                .writeTimeout(20000, TimeUnit.MILLISECONDS)
                .addInterceptor(interceptor)
//                .addInterceptor(publicParamInterceptor)
                .addInterceptor(new Interceptor() {
                    @Override
                    public Response intercept(Chain chain) throws IOException {
                        int maxAge = 60 * 60; // 有网络时 设置缓存超时时间1个小时
                        int maxStale = 60 * 60 * 24 * 28; // 无网络时，设置超时为4周
                        Request request = chain.request();
                        if (HttpUtils.isNetworkReachable(MyApplication.getInstance())) {
                            request = request.newBuilder()
                                    .cacheControl(CacheControl.FORCE_NETWORK)//有网络时只从网络获取
                                    .build();
                        } else {
                            request = request.newBuilder()
                                    .cacheControl(CacheControl.FORCE_CACHE)//无网络时只从缓存中读取
                                    .build();
                        }
                        Response response = chain.proceed(request);
                        if (HttpUtils.isNetworkReachable(MyApplication.getInstance())) {
                            response = response.newBuilder()
//                                    .header("Date", HttpSign.getGMTTime())
//                                    .header("Source", "android")
//                                    .header("Authorization", getTencentSign())
                                    .build();
                        } else {
                            response = response.newBuilder()
//                                    .header("Date", HttpSign.getGMTTime())
//                                    .header("Source", "android")
//                                    .header("Authorization", getTencentSign())
                                    .build();
                        }
                        return response;
                    }

                })
                .connectTimeout(2, TimeUnit.SECONDS)
//                .cache(cache)

                .build();
    }

    public <T> T create(Class<T> tClass) {
        return retrofit.create(tClass);
    }

    //自定义一个拦截器 封装公共请求参数
    private class PublicParamInterceptor implements Interceptor {

        Map<String, String> paramMap = new HashMap<>();

        public PublicParamInterceptor(Map<String, String> paramMap) {
            this.paramMap = paramMap;
        }

        @Override
        public Response intercept(Chain chain) throws IOException {
            //拿到原来的request
            Request oldRequest = chain.request();
            //拿到原来的url
            String url = oldRequest.url().toString();
            //判断是Get还是Post
            if (oldRequest.method().equalsIgnoreCase("GET")) {
                if (paramMap != null && paramMap.size() > 0) {
                    StringBuffer stringBuffer = new StringBuffer(url);
                    //拼接公共参数
                    for (Map.Entry<String, String> entry : paramMap.entrySet()) {
                        stringBuffer.append("&" + entry.getKey() + "=" + entry.getValue());
                    }
                    url = stringBuffer.toString();
                    //如果之前没有？号，手动给添加？
                    if (!url.contains("?")) {
                        url = url.replaceFirst("&", "?");
                    }
                    //根据原来的request构成新的request
                    Request request = oldRequest.newBuilder()
                            .url(url)
                            .build();
                    return chain.proceed(request);
                }
            } else {
                //Post请求
                if (paramMap != null && paramMap.size() > 0) {
                    RequestBody body = oldRequest.body();
                    if (body != null && body instanceof FormBody) {
                        FormBody formBody = (FormBody) body;
                        //1.把原来的的body里面的参数添加到新的body中
                        FormBody.Builder builder = new FormBody.Builder();
                        //为了防止重复添加相同的key和value
                        Map<String, String> temMap = new HashMap<>();
                        for (int i = 0; i < formBody.size(); i++) {
                            builder.add(formBody.encodedName(i), formBody.encodedValue(i));
                            temMap.put(formBody.encodedName(i), formBody.encodedValue(i));
                        }
                        //2.把公共请求参数添加到新的body中
                        for (Map.Entry<String, String> entry : paramMap.entrySet()) {
                            if (!temMap.containsKey(entry.getKey())) {
                                builder.add(entry.getKey(), entry.getValue());
                                builder.add(entry.getKey(), entry.getValue());
                            }
                        }
                        FormBody newFormBody = builder.build();
                        //依据原来的request构造一个新的request,
                        Request newRequest = oldRequest.newBuilder()
                                .post(newFormBody)
                                .build();
                        return chain.proceed(newRequest);
                    }
                }
            }


            return chain.proceed(oldRequest);
        }
    }

    /**
     * 配置签名数据
     *
     * @return
     */

    public static String getTencentSign() {
        String gmtTime = HttpSign.getGMTTime();
        String sig = null;
        try {
            sig = HttpSign.sign(UrlInterface.SECRETKEY, gmtTime, getSource());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }
        String authen = "hmac id=\"" + UrlInterface.SECRETID + "\", algorithm=\"hmac-sha1\", headers=\"date source\", signature=\"" + sig + "\"";
        return authen;
    }

    public static Map<String,String> getParams(){
        Map<String,String> params = new HashMap<>();
        StringBuilder builder = new StringBuilder();
        builder.append(PreferenceUtil.getInstance().getString(PreferenceUtil.BRAND_ID,""));
        builder.append("|");
        builder.append(PreferenceUtil.getInstance().getInt(PreferenceUtil.USER_ID,0));
        builder.append("|");
        builder.append(PreferenceUtil.getInstance().getString(PreferenceUtil.TOKEN,""));
        builder.append("|");
        builder.append(0);
        builder.append("|");
        params.put("brandtoken", builder.toString());
        params.put("timeStamp", System.currentTimeMillis() / 1000 + "");//加时间戳参数
        params.put("sign", MD5Util.md5(params));//md5加密并加参数
        return params;
    }

    public static Map<String,String> getHeader(){
        Map<String, String> header = new HashMap<>();
        header.put("Date", HttpSign.getGMTTime());
        header.put("Source", getSource());
//        header.put("Source", "android");
//        header.put("Authorization", getTencentSign());//有些接口要小写开头
        header.put("authorization", getTencentSign());//有些接口要大写开头
        return header;
    }

    /**
     * 新的post请求下的url拼接
     * @param url
     * @param params
     * @return
     */
    public static String getUrl(String url,Map params){
        StringBuilder sb = new StringBuilder(url);
        sb.append("?");
        sb.append("brandtoken="+params.get("brandtoken"));
        sb.append("&");
        sb.append("timeStamp="+params.get("timeStamp"));
        sb.append("&");
        sb.append("sign="+params.get("sign"));
        return sb.toString();
    }

    /**
     * 新接口下参数排除
     * @param params
     * @return
     */
    public static Map getNewParams(Map params){
        params.remove("brandtoken");
        params.remove("timeStamp");
        params.remove("sign");
        return params;
    }

    /**
     * 新网关Source
     */
    public static String getSource(){
        String packageName = MyApplication.getInstance().getPackageName();
        String versionName = "";
        try {
            PackageInfo packageInfo = MyApplication.getInstance().getPackageManager().getPackageInfo(MyApplication.getInstance().getPackageName(), 0);
            versionName = packageInfo.versionName;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        return "ANDROID_SCAN|"+packageName+"|"+versionName;
    }

}
